﻿using Microsoft.Extensions.Options;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using OpenQA.Selenium.BiDi.Modules.BrowsingContext;

namespace MoocProject
{
    class CrawService:ICrawService
    {
        public IWebDriver Driver { get; set; }
		public WebDriverWait Wait { get; set; }
        public CrawService(IWebDriver Driver)
        {
            this.Driver = Driver;
			Wait = new WebDriverWait(this.Driver,TimeSpan.FromSeconds(60));
        }
        public void GoToUrl(string url)
        {
            Driver.Navigate().GoToUrl(url);
			
		}
		public void GoToUrlFromNewWindow(string url)
		{
			Driver.SwitchTo().NewWindow(WindowType.Tab);
			Driver.Navigate().GoToUrl(url);
			
		}
		public async Task<IWebElement> GetElement(By selector)
		{
			return await Task.Run(() => Wait?.Until(d =>
			{
				var targetElement = d.FindElement(selector);
				return targetElement.Displayed && targetElement.Enabled ? targetElement : null;
			}));
		}

		public IWebElement GetElement(IWebElement element, By selector)
		{
			return element.FindElement(selector);
		}
		public IReadOnlyCollection<IWebElement> GetElements(IWebElement element, By selector)
		{
			return element.FindElements(selector);
		}
		public async Task<IReadOnlyCollection<IWebElement>> GetElements(By selector)
		{
			
			if (Driver == null)
			{
				throw new InvalidOperationException(nameof(Driver));
			}
			return await Task.Run(()=>Wait?.Until(d =>
			{
				var targetElement = d.FindElements(selector);
				return targetElement.All(d=>d.Displayed) && targetElement.All(d=>d.Enabled) ? targetElement : null;
			}));
		}
		public async Task SaveCookies()
		{
			string filePath=Driver.Url.Split('.')[1] + "_Cookie.json";
			if (File.Exists(filePath)) File.Delete(filePath);
			List<Cookie> cookies = new List<Cookie>(Driver.Manage().Cookies.AllCookies);
			var serializerOptions = new JsonSerializerOptions();
			serializerOptions.Converters.Add(new CookieConverter());
			string json = JsonSerializer.Serialize(cookies, serializerOptions);
			await File.WriteAllTextAsync(filePath, json);
		}
		
		public async Task<List<List<string>>> GetQuestionUrls()
		{
			By contextSelector = By.CssSelector("div.m-choiceQuestion.u-questionItem.examMode.first, div.m-choiceQuestion.u-questionItem.examMode,div.m-choiceQuestion.u-questionItem.examMode.last");
			var questionContexts = await GetElements(contextSelector);
			List<List<string>> questionUrls = new List<List<string>>();
			foreach (IWebElement Context in questionContexts)
			{
				By Title = By.CssSelector("div.j-title.title.f-cb img");
				var questionTitle = GetElement(Context, Title);
				By Options = By.CssSelector("div.j-choicebox ul li label");
				var questionOptions = GetElements(Context, Options);
				string TitleURL = questionTitle.GetAttribute("src");
				List<string> questionUrl = new List<string>();
				questionUrl.Add(TitleURL);

				foreach (IWebElement questionOption in questionOptions)
				{
					IWebElement questionOptionText = null;
					try
					{
						questionOptionText = questionOption.FindElement(By.CssSelector("p img"));
						string OptionURL = questionOptionText.GetAttribute("src");
						questionUrl.Add(OptionURL);
					}
					catch
					{
						continue;
					}
				}
				questionUrls.Add(questionUrl);
			}
			return questionUrls;
		}
		public async Task LoadCookiesFromFile()
		{
			string filePath = Driver.Url.Split('.')[1] + "_Cookie.json";
			if (!File.Exists(filePath))
			{
				MessageBox.Show("Cookie文件未保存","温馨提示",MessageBoxButtons.OK);
				return;
			}

			try
			{
				// 读取JSON文件
				string json = await File.ReadAllTextAsync(filePath);

				// 配置序列化选项
				var options = new JsonSerializerOptions
				{
					Converters = { new CookieConverter() }
				};

				// 反序列化为Cookie列表
				var cookies = JsonSerializer.Deserialize<List<Cookie>>(json, options);

				if (cookies == null || !cookies.Any())
				{
					MessageBox.Show("Cookie列表为空");
					return;
				}


				// 添加Cookie到WebDriver
				foreach (var cookie in cookies)
				{
					try
					{
						// 跳过已过期的Cookie
						if (cookie.Expiry.HasValue && cookie.Expiry.Value < DateTime.Now)
						{
							MessageBox.Show($"跳过已过期的Cookie: {cookie.Name}");
							continue;
						}

						Driver.Manage().Cookies.AddCookie(cookie);
					}
					catch (Exception ex)
					{
						MessageBox.Show($"添加Cookie时出错: {cookie.Name} - {ex.Message}");
					}
				}


				// 刷新页面使Cookie生效
				Driver.Navigate().Refresh();
			}
			catch (Exception ex)
			{
				MessageBox.Show($"加载Cookie文件时出错: {ex.Message}");
			}
		}
		public void CopyImageToBox()
		{
			Actions actions = new Actions(Driver);
			actions.KeyDown(OpenQA.Selenium.Keys.Control).SendKeys("v").KeyUp(OpenQA.Selenium.Keys.Control).Perform();
		}
		public void ScrollToEnd()
		{
			IJavaScriptExecutor js = (IJavaScriptExecutor)Driver;
			js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
		}
		public void Dispose()
		{
			Driver?.Dispose();
			GC.SuppressFinalize(this);
		}
	}
}
